package main

import (
	"encoding/json"
	"fmt"
)

// 1.struct的字段在内存中地址是连续的
// 2.两个结构体是不同的类型，可以强转，但是字段要完全相同
// 3.使用tag，tag可以反射，例如可以序列化和反序列化 json.Marshal
func main() {
	testAddr01()
	//testAddr02()
	testCast03()
	//testSer04()
}

// struct的字段在内存中地址是连续的
func testAddr01() {
	var r1 Rect = Rect{Point{1, 2}, Point{3, 4}}
	fmt.Printf("%p %p %p %p \n", &r1.LeftUp.X, &r1.LeftUp.Y, &r1.RightDown.X, &r1.RightDown.Y)
	//0xc0000121c0 0xc0000121c8 0xc0000121d0 0xc0000121d8  struct的字段在内存中地址是连续的
}

// struct的字段在内存中地址是连续的
func testAddr02() {

	var r2 Rect2 = Rect2{&Point{1, 2}, &Point{3, 4}}
	fmt.Printf("%p %p \n", &r2.LeftUp, &r2.RightDown) //0xc00008e2a0 0xc00008e2a8 两者本身的地址是连续的
	fmt.Printf("%p %p \n", r2.LeftUp, r2.RightDown)   //但是指向的地址：不一定连续
}

// 这两个结构体是不同的类型
func testCast03() {
	a := A{1}
	b := B{1}
	fmt.Println(a)
	fmt.Println(b)
	//fmt.Println(a == b) //报错 Invalid operation: a == b (mismatched types A and B)
	a = A(b) //强转可以，但是必须有完全相同的字段  （非值类型的强转）
	fmt.Println(a)
	fmt.Println(b)

}

// 使用标签tag，tag可以反射，例如可以序列化和反序列化
func testSer04() {
	monster := Monster{"牛魔王", 120, "芭蕉扇"}
	//序列化
	jsonStr, err := json.Marshal(monster)
	if err != nil {
		fmt.Println("json-error", err)
	}
	fmt.Println(string(jsonStr))

	//反序列化

}

// Point struct的字段在内存中地址是连续的
type Point struct {
	X int
	Y int
}

type Rect struct {
	LeftUp    Point
	RightDown Point
}

type Rect2 struct {
	LeftUp    *Point // 指针类型
	RightDown *Point // 指针类型
}

type A struct {
	Num int
}

type B struct {
	Num int
}

// Monster 使用tag前  {"Name":"牛魔王","Age":120,"Skill":"芭蕉扇"}
// 使用tag后 {"name":"牛魔王","age":120,"skill":"芭蕉扇"}
type Monster struct {
	Name  string `json:"name"`
	Age   int    `json:"age"`
	Skill string `json:"skill"`
}
